package cn.huijielong.modules.app.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClaims;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import cn.huijielong.common.exception.VSException;
import cn.huijielong.common.props.PropsConfig;
import cn.huijielong.common.utils.EncryptUtil;
import cn.huijielong.common.utils.Query;
import cn.huijielong.modules.sys.entity.SysUserEntity;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt工具类
 * @date 2017/9/21 22:21
 */
@Component
public class JwtUtils {
	@Autowired
	private PropsConfig propsConfig;
	
    private Logger logger = LoggerFactory.getLogger(getClass());

    private EncryptUtil encryptUtil;
    
    //userId(0),roleId(1),enterpriseId(3),roleType(4),userKey(5)
      public static final String XTUSER = "xtuser";
      
      private final static String SEPARATOR=",";

      public void init() {
      	try {
  			encryptUtil=new EncryptUtil(propsConfig.getJwt().getSecret());
  		} catch (Exception e) {
  			throw new VSException("加密类初始化失败",e);
  		}
  	}
      /**
       * 生成jwt token
       */
      public String generateToken(long userId,Date expireDate) {
          Date nowDate = new Date();
          return Jwts.builder()
                  .setHeaderParam(Header.TYPE, Header.JWT_TYPE)
                  .setSubject(userId+"")
                  .setIssuedAt(nowDate)
                  .setExpiration(expireDate)
                  .signWith(SignatureAlgorithm.HS512, propsConfig.getJwt().getSecret())
                  .compact();
      }
      
      public String generateToken(long userId,Date expireDate,Map<String,Object> data) {
      	
      	Claims claims = new DefaultClaims();
      	claims.setSubject(String.valueOf(userId))
      	.setIssuedAt(new Date())
      	.setExpiration(expireDate);
      	if(data!=null)
      		claims.putAll(data);
      	return Jwts.builder()
      			.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
      			.setClaims(claims)
      			.signWith(SignatureAlgorithm.HS512, propsConfig.getJwt().getSecret())
      			.compact();
      }
      
   
      public String generateToken(SysUserEntity user) {
      	//过期时间
      	Date expireDate = new Date(new Date().getTime() + propsConfig.getJwt().getExpire() * 1000);
      	return generateToken( expireDate, user);
      }

      public String generateToken(Date expireDate,SysUserEntity user) {
      	
      	Map<String,Object> data=new HashMap<>();
      	StringBuilder suser=new StringBuilder();
      	suser.append(user.getUserId());
      	suser.append(SEPARATOR).append(user.getMerchantId()==null?0:user.getMerchantId());
      	suser.append(SEPARATOR).append(user.getUserKey()==null?"":user.getUserKey());
      	//userId(0),merchantId(1),userKey(2)
  		try {
  			//对用户敏感数据进行加密处理
  			String userStr = encryptUtil.encode(suser.toString());
  			data.put(XTUSER, userStr);
  		} catch (Exception e) {
  			logger.error("token信息加密失败",e);
  			return null;
  		}
      	
      	return generateToken(user.getUserId(),expireDate,data);
      }
      public Claims getClaimByToken(String token) {
          try {
              return Jwts.parser()
                      .setSigningKey(propsConfig.getJwt().getSecret())
                      .parseClaimsJws(token)
                      .getBody();
          }catch (Exception e){
              logger.error("validate is token error ", e);
              return null;
          }
      }

      /**
       * token是否过期
       * @return  true：过期
       */
      public boolean isTokenExpired(Date expiration) {
          return expiration.before(new Date());
      }


      public static int getInt(Claims claims,String key) {
      	if(claims==null)
      		return 0;
      	Object v=claims.get(key);
      	if(v==null)
      		return 0;
      	else if(v instanceof Integer)
      		return (Integer)v;
      	else
      		return 0;
      }
      public static Long getLong(Claims claims,String key) {
      	if(claims==null)
      		return 0L;
      	Object v=claims.get(key);
      	if(v==null)
      		return 0L;
      	else if(v instanceof Long)
      		return (Long)v;
      	else
      		return 0L;
      }
      public static String getString(Claims claims,String key) {
      	if(claims==null)
      		return "";
      	Object v=claims.get(key);
      	if(v==null)
      		return "";
      	return v.toString();
      }
      public SysUserEntity getUser(Claims claims) {
      	//userId(0),merchantId(1),userKey(2)
      	SysUserEntity user=new SysUserEntity();
      	Object v=claims.get(XTUSER);
      	if(v!=null) {
  			try {
  				String destr = encryptUtil.decode(v.toString());
  				String[] us=destr.split(SEPARATOR);
  	    		user.setUserId(Long.valueOf(us[0]));
  	    		user.setMerchantId(Long.parseLong(us[1]));
  	    		user.setUserKey(us[2]);
  			} catch (Exception e) {
  				logger.error("从token解析用户信息出错："+v,e);
  			}
      		
      	}
      	return user;
      }
}
